﻿#include"stdafx.h"
#ifdef LK_FUNCTIONAL_ACTION_
namespace LK
{
	namespace Functional
	{
		/**
		@brief 使用指定的委托和参数数组来创建*/
		PActions::PActions(PDelegates d, Collection::PArray<PObject> args)
			:PFunObject<WeakPtr<PActions>, VarArgsPack<void, void>, true>(new IActions())
		{
			if (d.IsNull())throw PInvalidArgumentException(L"指定的委托为空");
			GetPtr()->delegates = d;
			GetPtr()->args = args;
		}
		/**
		@brief 同步执行动作*/
		void PActions::Do() const { Ptr()->Do(); }
		/**
		@brief 同步执行动作，同Do()*/
		void PActions::operator()()const { Do(); }
		/**
		@brief 启动一个新线程来异步执行动作*/
		DWORD PActions::DoSync()const { return Ptr()->DoSync(); }
		/**
		@brief 获取返回值的引用*/
		PObject& PActions::GetReturnValRef()const { return Ptr()->returnVal; }
		/**
		@brief 获取内部委托的引用*/
		PDelegates& PActions::GetDelegateRef()const { return Ptr()->delegates; }
		/**
		@brief 获取参数列表数组的引用*/
		LK::Collection::PArray<PObject>& PActions::GetArgumentsRef()const { return Ptr()->args; }
		PActions PActions::GetNextActionRef()const { return Ptr()->nextAction; }
		void PActions::Clear()const { Ptr()->Clear(); }
		/**
		@brief 获取动作当前状态的引用（不一定是准确的，因为获取状态的瞬间可能发生改变）*/
		index_t&  PActions::GetStateRef()const { return Ptr()->state; }
		/**
		@brief 获取动作已执行的次数的引用（不一定是准确的，，因为获取状态的瞬间可能发生改变）*/
		index_t&  PActions::GetDidCountRef()const { return Ptr()->didCnt; }
		/**
		@brief 默认构造函数*/
		IActions::IActions() :FunObject<WeakPtr<PActions>, VarArgsPack<void, void>, true>((IActions*)NULL), didCnt(0), state(0)
		{
			FunObject<WeakPtr<PActions>, VarArgsPack<void, void>, true>::pfun = ((IActions*)this);
		}
		/**
		@brief 复制构造函数*/
		IActions::IActions(IActions const&act) :FunObject<WeakPtr<PActions>, VarArgsPack<void, void>, true>((IActions*)NULL), didCnt(0), state(0)
		{
			FunObject<WeakPtr<PActions>, VarArgsPack<void, void>, true>::pfun = this;
			delegates = act.delegates;
			returnVal = act.returnVal;
			args = act.args;
		}
		/**
		@brief 同步执行动作*/
		void IActions::Do() { returnVal = delegates.Invoke(PObject(), args); }
		/**
		@brief 启动一个新线程来异步执行动作*/
		DWORD IActions::DoSync()
		{
			IActions* pAct = this;
			DWORD id = APIStartThread(&IActions::ThreadFunction, &pAct);
			while (pAct)Sleep(0);
			return id;
		}
		void IActions::ThreadFunction(void*p)
		{
			PActions act = *(IActions**)p;
			*(IActions**)p = NULL;
			act.Do();
		}
		void IActions::Clear()
		{
			if (!args.IsNull())args.clear();
			args.SetToNull();
			delegates.SetToNull();
			nextAction.SetToNull();
			returnVal.SetToNull();
			didCnt = 0;
			state = 0;
		}

	}
}
#endif
